package user;

import net.rim.device.api.command.CommandHandler;
import net.rim.device.api.command.ReadOnlyCommandMetadata;
import net.rim.device.api.ui.component.CheckboxField;
import sources.AccelerometerSource;
import sources.DeterministicSource;
import sources.MagnetometerSource;
import sources.MicrophoneSource;
import sources.RandomSource;
import sources.SourceThread;

public class GeneratorUser extends CommandHandler {
	
	private static final RandomSource[] sources = new RandomSource[]{
			new DeterministicSource(),
			new AccelerometerSource(),
			new MagnetometerSource(),
			new MicrophoneSource()
			//new FmRadioStrengthSource() Don't have an FM Radio on my blackberry I guess
	};
	
	private final SaveStrategy[] saveStrategies = new SaveStrategy[]{
			new EmailSaveStrategy()
	};
	
	// Modularity would have me using a Map<String, Boolean> here, but I'm being lazy
	// as I don't intend to use GeneratorUser anywhere else ever
	private CheckboxField[] enabledSources = null;
	private long stopTime = 0;
	
	public GeneratorUser(CheckboxField[] sources, long stopTime) {
		enabledSources = sources;
		this.stopTime = stopTime;
	}

	public void execute(ReadOnlyCommandMetadata metadata, Object context) {
		Thread[] runningSources = startSources();
		waitFor(runningSources);
		saveData();
		clearData(); // Because I'm being silly and using a static list >_>
	}

	private void clearData() {
		for(int i = 0; i < sources.length; i++){
			sources[i].clearBuffers();
		}
	}

	private void saveData() {
		for(int i = 0; i<sources.length; i++){
			if(isEnabled(sources[i])){
				for(int j = 0; j<saveStrategies.length; j++){
					saveStrategies[j].save(sources[i]);
				}
			}
		}
	}

	private Thread[] startSources() {
		Thread[] runningSources = new Thread[sources.length];
		for(int i = 0; i < sources.length; i++){
			if(isEnabled(sources[i])){
				runningSources[i] = new SourceThread(sources[i], stopTime);
				runningSources[i].start();
			}
		}
		return runningSources;
	}

	// TODO Progress info and cancel ability
	private void waitFor(Thread[] threads) {
		for(int i = 0; i < threads.length; i++){
			if(threads[i] != null){
				try {
					threads[i].join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private boolean isEnabled(RandomSource randomSource) {
		for(int i = 0; i < enabledSources.length; i++){
			if(enabledSources[i].getChecked() && enabledSources[i].getLabel().equals(randomSource.getSourceName())){
				return true;
			}
		}
		return false;
	}

	public static String[] getSourceNames() {
		String[] sourceNames = new String[sources.length];
		for(int i = 0; i < sources.length; i++){
			sourceNames[i] = sources[i].getSourceName();
		}
		return sourceNames;
	}

}
